package com.xuzhiguang.light.gateway.server.http.netty;

import com.xuzhiguang.light.gateway.common.request.GatewayRequest;
import com.xuzhiguang.light.gateway.common.request.RequestContext;
import com.xuzhiguang.light.gateway.common.response.AbstractHttpGatewayResponse;
import com.xuzhiguang.light.gateway.common.response.GatewayResponse;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.handler.codec.http.DefaultFullHttpResponse;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import io.netty.util.ReferenceCountUtil;

import static io.netty.handler.codec.http.HttpVersion.HTTP_1_1;

/**
 * @author xuzhiguang
 */
public class NettyHttpRequestContext implements RequestContext {

    private final static HttpResponseStatus DEFAULT = HttpResponseStatus.OK;

    private final ChannelHandlerContext context;

    public NettyHttpRequestContext(ChannelHandlerContext context) {
        this.context = context;
    }

    @Override
    public void writeAndFlush(GatewayResponse response) {
        context.writeAndFlush(toHttpResponse(response));
    }

    @Override
    public void releaseRequest(GatewayRequest gatewayRequest) {
        ReferenceCountUtil.release(gatewayRequest.getOriginalRequest());
    }

    private HttpResponse toHttpResponse(GatewayResponse response) {

        HttpResponseStatus status = DEFAULT;
        if (response instanceof AbstractHttpGatewayResponse) {
            status = HttpResponseStatus.valueOf(((AbstractHttpGatewayResponse) response).getStatusCode());
        }

        ByteBuf content;

        if (response.getBody() != null) {
            content = Unpooled.wrappedBuffer(response.getBody());
        } else {
            content = Unpooled.buffer(0);
        }

        HttpResponse httpResponse = new DefaultFullHttpResponse(HTTP_1_1, status, content);

        response.getHeaders().forEach((s, o) -> httpResponse.headers().add(s, o));

        return httpResponse;
    }
}
